// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement.  The various license agreements may be found at
// the Magic Software web site.  This file is subject to the license
//
// RESTRICTED USE SOURCE CODE
// http://www.magic-software.com/License/restricted.pdf

#ifndef MGCTUBESURFACE_H
#define MGCTUBESURFACE_H

#include "MgcTriMesh.h"
class MgcMultipleCurve3;


class MgcTubeSurface : public MgcTriMesh
{
    MgcDeclareRTTI;
    MgcDeclareStream;

public:
    typedef MgcReal (*RadialFunction)(MgcReal);

    // Construction and destruction.  MgcTubeSurface accepts responsibility
    // for deleting the input curve.  If rkUpVector references a vector that
    // is not (0,0,0), it will be used as 'up' in the frame calculations.  If
    // it does reference (0,0,0), the Frenet frame will be used.
    MgcTubeSurface (MgcMultipleCurve3* pkMedial, RadialFunction oRadial,
        bool bClosed, unsigned int uiMedialSamples,
        unsigned int uiSliceSamples, bool bSampleByArcLength,
        bool bWantNormals, const MgcVector3& rkUpVector,
        const MgcVector2& rkTextureMin, const MgcVector2& rkTextureMax);

    virtual ~MgcTubeSurface ();

    // curve access
    MgcMultipleCurve3*& Medial ();
    const MgcMultipleCurve3* Medial () const;
    RadialFunction& Radial ();
    RadialFunction Radial () const;
    bool& Closed ();
    bool Closed () const;

    // Tessellation.  If no up vector is specified, the tessellation uses
    // the Frenet frame to generate the surface.  Otherwise the up vector
    // and tangent vector are used to generate frames.
    void Tessellate (unsigned int uiMedialSamples,
        unsigned int uiSliceSamples, bool bSampleByArcLength,
        bool bWantNormals, const MgcVector3& rkUpVector,
        const MgcVector2& rkTextureMin, const MgcVector2& rkTextureMax);

    unsigned int GetMedialSamples () const;
    unsigned int GetSliceSamples () const;
    bool GetSampleByArcLength () const;
    bool GetWantNormals () const;
    const MgcVector3& GetUpVector () const;
    const MgcVector2& GetTextureMin () const;
    const MgcVector2& GetTextureMax () const;

protected:
    MgcTubeSurface ();

    // tessellation
    unsigned int Index (unsigned short uiS, unsigned short uiM);
    void ComputeVertices (unsigned int& ruiVertexQuantity,
        MgcVector3*& rakVertex);
    MgcVector3* ComputeNormals (unsigned int uiVertexQuantity,
        MgcVector3* akVertex);
    MgcVector2* ComputeTextures (unsigned int uiVertexQuantity);
    void ComputeConnectivity (unsigned int& ruiTriangleQuantity,
        unsigned int*& rauiConnect);

    // curve data
    MgcMultipleCurve3* m_pkMedial;
    RadialFunction m_oRadial;
    bool m_bClosed;

    // tessellation data
    unsigned int m_uiMedialSamples;
    unsigned int m_uiSliceSamples;
    bool m_bSampleByArcLength;
    bool m_bWantNormals;
    MgcVector3 m_kUpVector;
    MgcVector2 m_kTextureMin;
    MgcVector2 m_kTextureMax;
};

#include "MgcTubeSurface.inl"

#endif
